import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import com.csvreader.CsvReader;

import wrapper.*;
import common.*;


/**
 * @author Or Kaplan
 * wrapper for insert command - insert to temp table, join with real table and delete the temp
 */
public class InsertStatementWrapper {
	private PreparedStatement insertTempStatement;
	private PreparedStatement joinTempStatement;
	private PreparedStatement deleteTempStatement;
	
	private String insertSql;
	private String joinSql;
	private String deleteSql;
	private String tableName; 
	
	/**
	 * @param tableName
	 * @param insertSql
	 * @param joinSql
	 * @param deleteSql
	 */
	public InsertStatementWrapper(String tableName, String insertSql, String joinSql, String deleteSql)
	{
		this.insertSql = insertSql;
		this.joinSql = joinSql;
		this.deleteSql = deleteSql;
		this.tableName = tableName;
	}
	
	/**
	 * @param conn
	 * @throws SQLException
	 */
	public void prepareStatements(Connection conn) throws SQLException 
	{
		this.joinTempStatement = conn.prepareStatement(this.joinSql);
		this.insertTempStatement = conn.prepareStatement(this.insertSql);
		
		this.deleteTempStatement = conn.prepareStatement(deleteSql);
		deleteTempStatement.executeUpdate();
	}
	
	/**
	 * insert to temp, join to real table (insert only new items), delete temp table
	 * @throws SQLException
	 */
	public void executeCommand() throws SQLException
	{
		deleteTempStatement.executeUpdate();
		
		insertTempStatement.executeBatch();
		insertTempStatement.close();
		
		joinTempStatement.executeUpdate();
		joinTempStatement.close();
		
		deleteTempStatement.executeUpdate();
		deleteTempStatement.close();
	}
	
	/**
	 * insert all fields to statement and add it to batch
	 * @param fields
	 * @param reader
	 * @return true - success, false failure
	 */
	public boolean InsertRecord(List<IFieldWrapper> fields, CsvReader reader) {
		try {
			for (int i = 0; i < fields.size(); i++) {
					if (!fields.get(i).insertToStatement(this.insertTempStatement, i+1, reader)) {
						Logger.GetLogger().Log("invalid value at table " + this.tableName + ", id " + reader.get(fields.get(0).getTsvFieldName()));
						return false;
					}
			}
			this.insertTempStatement.addBatch();
		} catch (IOException e) {
			return false;
		} catch (SQLException e) {
			return false;
		}
		return true;
	}
	
	/**
	 * insert all values to statement and add it to batch
	 * @param fields
	 * @param values
	 * @return true - success, false failure
	 */
	public boolean InsertRecord(List<IFieldWrapper> fields, String[] values) {
		try {
			for (int i = 0; i < fields.size(); i++) {
				if (!fields.get(i).insertToStatement(this.insertTempStatement, i+1, values[i])) {
					Logger.GetLogger().Log("invalid value at table " + this.tableName + ", id " + values[0]);
					return false;
				}
			}
			this.insertTempStatement.addBatch();
		} catch (SQLException e) {
			return false;
		}
		return true;
	}
}
